import React, { Component } from 'react'
import ResizeObserver from 'rc-resize-observer';
import { Layout, Button, Dropdown, Tooltip, Space } from 'antd';
import { TableOutlined, SaveOutlined } from '@ant-design/icons';
import ReactEcharts from 'echarts-for-react';
import dayjs from 'dayjs'
import _ from 'lodash'

import './CurveChart.css'

import PlanDialog from './PlanDialog'
import VirtualTable from './VirtualTable'

import SparkChannel, { EE } from 'src/ipc/sparkchannel'
import { DATE_FMT } from 'src/core/common'
import { exportTableToExcel } from './export'

const { Content, Header, Sider } = Layout;

function defaultChartOption() {
  return {
    legend: {
      // type: 'scroll',
      orient: 'horizontal',
      top: 20
    },
    tooltip: {
      trigger: 'axis',
      // triggerOn: 'click',
      // alwaysShowContent: true,
      valueFormatter: (value) => {
        return value instanceof Number ? value.toFixed(2) : value;
      }
    },
    xAxis: {
    },
    yAxis: {
      type: 'value',
    },
    dataZoom: [
      {
        type: 'inside',
        start: 0,
        end: 100,
      },
      {
        start: 0,
        end: 100,
      }
    ],
  };
}

const TIME_COLUMU = {
  title: '时间',
  dataIndex: 'timeLabel',
  width: 160,
  key: 'time',
  ellipsis: true,
};

class CurveHelper {
  constructor(plan, points) {
    this.plan = plan;
    this.points = points;
    this.timeMap = null;
    this.tableColumn = null;
    this.tableWidth = 0;
    this.todayBase = dayjs().startOf('day');
    this.preProcess();
  }

  preProcess() {
    const plan = this.plan;
    const timeRows = {};
    const columns = [TIME_COLUMU];
    const colWidth = 120;

    // add timeLabel
    for (const pt of this.points) {
      const { key, title } = this.getSeries(pt);
      const ref = dayjs(pt.date, 'YYYY-MM-DD');

      columns.push({
        title: title,
        dataIndex: key,
        key: key,
        width: colWidth,
        ellipsis: true,
      });

      for (const value of pt.values) {
        const num = Number(value.value);
        const dj = plan.mode_type === 'HOUR_BAR' || plan.mode_type === 'DAY_BAR' ?
          dayjs(value.time, DATE_FMT) : dayjs(parseInt(value.time));//棒图和曲线图返回的time格式不一样
        if (plan.picker_type === 'COMPRANGE') {
          const hourDj = this.todayBase.add(dj.diff(ref), 'millisecond');
          value.timeLabel = hourDj.format('HH:mm');
          value.timeDate = hourDj.toDate();
        } else {
          if (plan.mode_type === 'HOUR_BAR') {
            value.timeLabel = dj.format('YYYY-MM-DD HH:mm');
          } else if (plan.mode_type === 'DAY_BAR') {
            value.timeLabel = dj.format('YYYY-MM-DD');
          } else {
            value.timeLabel = dj.format(DATE_FMT);
          }
          value.timeDate = dj.toDate();
        }

        const timeLabel = value.timeLabel;
        let row = timeRows[timeLabel];
        if (!row) {
          row = { timeLabel: timeLabel, key: timeLabel };
          timeRows[timeLabel] = row;
        }
        row[key] = num;
      }
    }

    this.timeMap = timeRows;
    this.tableColumn = columns;
    this.tableWidth = Math.min(TIME_COLUMU.width + this.points.length * colWidth, 600);
  }

  getSeries(point) {
    if (this.plan.picker_type === 'COMPRANGE') {
      const key = `${point.point_id}-${point.date}`;
      const title = `${point.station_desc}/${point.bay_desc}/${point.device_desc}/${point.point_desc} ${point.date}`;
      return { key, title };
    } else {
      const key = point.point_id;
      const title = `${point.station_desc}/${point.bay_desc}/${point.device_desc}/${point.point_desc}`;
      return { key, title };
    }
  }

  buildTableData() {
    const tableColumn = this.tableColumn;
    const tableData = _.sortBy(Object.values(this.timeMap), row => row.timeLabel);
    const tableWidth = this.tableWidth;
    return { tableData, tableColumn, tableWidth };
  }

  buildLineChartOption() {
    const plan = this.plan;
    const points = this.points;
    const chartOption = defaultChartOption();
    chartOption.xAxis = {
      type: 'time',
      boundaryGap: false,
    };
    chartOption.yAxis.scale = true;

    chartOption.series = points.map(pt => {
      const data = pt.values.map(v => {
        const num = Number(v.value);
        return [v.timeDate, num];
      });

      const { title } = this.getSeries(pt);
      const s = {
        name: title,
        type: 'line',
        smooth: true,
        // symbol: 'none',
        showSymbol: false,
        data: data,
      };
      if (plan.mode_type === 'SECOND_CURVE') {
        s.sampling = 'average';
      }
      return s;
    });

    if (plan.picker_type === 'DATE') {
      chartOption.xAxis.axisLabel = { formatter: '{HH}:{mm}' };
    } else if (plan.picker_type === 'RANGE') {
      chartOption.xAxis.axisLabel = { formatter: '{yyyy}-{MM}-{dd}\n{HH}:{mm}' };
      chartOption.grid = { bottom: 80 };
    } else if (plan.picker_type === 'COMPRANGE') {
      chartOption.xAxis.axisLabel = { formatter: '{HH}:{mm}' };
      const valueFormatter = chartOption.tooltip.valueFormatter;
      chartOption.tooltip.formatter = function (params, ticket, callback) {
        const ts = params[0].axisValue;
        const title = dayjs(ts).format('HH:mm:ss');
        let res = `<div style="font-size:14px;color:#666;font-weight:400;line-height:1;">${title}</div>
        <div style="margin: 10px 0 0;line-height:1;clear:both"></div>`;
        for (var i = 0; i < params.length; i++) {
          const pm = params[i];
          const value = pm.value[pm.encode.y[0]];
          const valueLabel = valueFormatter ? valueFormatter(value) : value;
          res += `<span style="font-size:14px;color:#666;font-weight:400;margin-left:2px">${pm.seriesName}</span>
          <span style="float:right;margin-left:20px;font-size:14px;color:#666;font-weight:900">${valueLabel}</span>
          <div style="clear:both"></div>`;
          // res += "<br>" + params[i].marker + params[i].seriesName + "：" + params[i].data[1];
        }
        return res;
      };
      chartOption.dataZoom[1].labelFormatter = function (value, valueStr) {
        return dayjs(value).format('HH:mm:ss');
      };
    }

    return { chartOption };
  }

  buildBarChartOption() {
    const points = this.points;
    const chartOption = defaultChartOption();
    chartOption.xAxis = {};

    // 计算所有的时间点
    const timeRows = this.timeMap;
    const timeData = _.sortBy(Object.keys(timeRows));// array of timeLabel
    chartOption.xAxis.data = timeData;
    chartOption.series = points.map(pt => {
      const { key, title } = this.getSeries(pt);
      const data = timeData.map(timeLabel => {
        const row = timeRows[timeLabel];
        return row[key];
      });

      return {
        name: title,
        type: 'bar',
        data: data,
      };
    });

    return { chartOption };
  }
}


class CurveChart extends Component {
  constructor(props) {
    super(props);

    this.onResize = this.onResize.bind(this);
    this.triggerTable = this.triggerTable.bind(this);
    this.exportImage = this.exportImage.bind(this);
    this.exportExcel = this.exportExcel.bind(this);
    this.loadCurve = this.loadCurve.bind(this);
    this.showPlanDialog = this.showPlanDialog.bind(this);
    this.hidePlanDialog = this.hidePlanDialog.bind(this);
    this.saveQueryPlan = this.saveQueryPlan.bind(this);

    this.containerRef = React.createRef();
    this.echartRef = React.createRef();

    this.state = {
      title: '',
      tableCollapsed: true,
      tableWidth: 200,
      tableHeadHeight: 39,
      contentHeight: 200,
      contentWidth: 200,
      tableData: [],
      tableColumn: [TIME_COLUMU],
      chartOption: {},
      loading: false,

      planDialogOpen: false,
      plan: null,
    };
  }

  async loadCurve(plan) {
    console.log('loadCurve', plan);

    const title = plan.name;
    const point_list = plan.point_list;
    this.setState({ loading: true, title, plan });

    const channel = await SparkChannel();
    if (plan.mode_type === 'GENERAL_CURVE') {
      const resp = await channel.request_get_general_data_curve({
        picker_type: plan.picker_type,
        data_interval: plan.data_interval,
        interval_unit: plan.interval_unit,
        from: plan.from.format(DATE_FMT),
        to: plan.to.format(DATE_FMT),
        point_list,
      });
      const points = resp.data.point_list;

      const helper = new CurveHelper(plan, points);
      this.setState({
        ...helper.buildLineChartOption(),
        ...helper.buildTableData()
      });
    } else if (plan.mode_type === 'SECOND_CURVE') {
      const resp = await channel.request_get_second_data_curve({
        picker_type: plan.picker_type,
        from: plan.from.format(DATE_FMT),
        to: plan.to.format(DATE_FMT),
        point_list,
      });
      const points = resp.data.point_list;

      const helper = new CurveHelper(plan, points);

      this.setState({
        ...helper.buildLineChartOption(),
        ...helper.buildTableData()
      });
    } else if (plan.mode_type === 'HOUR_BAR' || plan.mode_type === 'DAY_BAR') {
      const resp = await channel.request_get_data_bar({
        picker_type: plan.picker_type,
        from: plan.from.format(DATE_FMT),
        to: plan.to.format(DATE_FMT),
        point_list,
        mode_type: plan.mode_type,
      });
      const points = resp.data.point_list;

      const helper = new CurveHelper(plan, points);
      this.setState({
        ...helper.buildBarChartOption(),
        ...helper.buildTableData()
      });
    }

    this.setState({ loading: false });
  }

  componentDidMount() {
    EE.on('open-curve', this.loadCurve);
  }

  componentWillUnmount() {
    EE.removeListener('open-curve', this.loadCurve);
  }

  componentDidUpdate() {
    const { tableHeadHeight } = this.state;
    const tableHead = this.containerRef.current?.querySelector(".virtual-table .ant-table-thead");
    if (tableHead &&
      tableHead.clientHeight &&
      tableHead.clientHeight !== tableHeadHeight) {
      // 如果高度有变化重新设置高度
      this.setState({ tableHeadHeight: tableHead.clientHeight });
    }
  }

  onResize(size) {
    // console.log('onResize', size);
    // const echart = this.echartRef.current.getEchartsInstance();
    // echart.resize();

    if (size) {
      this.setState({
        contentWidth: size.width,
        contentHeight: size.height,
      });
    }
  }

  triggerTable() {
    this.setState((state, props) => ({
      tableCollapsed: !state.tableCollapsed
    }));
  }

  exportImage() {
    console.log('exportImage');
    const { title } = this.state;
    const fileName = title.replace(new RegExp('/', 'gm'), '_');
    const echart = this.echartRef.current.getEchartsInstance();
    var picInfo = echart.getDataURL({
      type: 'png',
      pixelRatio: 2,  //放大两倍下载，之后压缩到同等大小展示。解决生成图片在移动端模糊问题
      backgroundColor: '#fff',
      excludeComponents: ['toolbox'] //忽略toolbox
    });//获取到的是一串base64信息
    var elink = document.createElement('a')
    elink.download = fileName;
    elink.style.display = 'none';
    elink.href = picInfo;
    document.body.appendChild(elink);
    elink.click();
    URL.revokeObjectURL(elink.href); // 释放URL 对象
    document.body.removeChild(elink);
  }

  exportExcel() {
    // console.log('exportExcel');
    const { title, tableColumn, tableData } = this.state;
    const fileName = title.replace(new RegExp('/', 'gm'), '_');
    exportTableToExcel(tableColumn, tableData, fileName);
  }

  showPlanDialog() {
    this.setState({ planDialogOpen: true });
  }
  hidePlanDialog() {
    this.setState({ planDialogOpen: false });
  };
  async saveQueryPlan(plan) {
    const channel = await SparkChannel();
    const resp = await channel.request_insert_curve_plan({
      name: plan.name,
      picker_type: plan.picker_type,
      mode_type: plan.mode_type,
      data_interval: plan.data_interval,
      interval_unit: plan.interval_unit,
      point_list: plan.point_list,
    });
    console.log('insert curve plan success', resp);

    this.hidePlanDialog();

    EE.emit('plan-list-changed');
  }

  render() {
    const state = this.state;
    const tableScrollY = state.contentHeight - state.tableHeadHeight;

    return (
      <div className='chart-wrapper' ref={this.containerRef}>
        <Layout >
          <Header className='chart_info_detail'>
            <div className='chart_name'>{state.title}</div>
            <Space>
              <Tooltip title="表格查询">
                <Button
                  type={state.tableCollapsed ? 'default' : 'primary'}
                  shape="circle"
                  icon={<TableOutlined />}
                  onClick={this.triggerTable} />
              </Tooltip>
              <Tooltip title="保存为查询计划">
                <Button
                  disabled={!state.plan}
                  shape="circle"
                  icon={<SaveOutlined />}
                  onClick={this.showPlanDialog} />
              </Tooltip>
              <Dropdown.Button
                disabled={!state.plan}
                onClick={this.exportImage}
                menu={{
                  items: [
                    {
                      key: 'excel',
                      label: '导出Excel',
                    }
                  ],
                  onClick: this.exportExcel,
                }}
              >
                导出图片
              </Dropdown.Button>

              {/* <Tooltip title="导出">
                                <Button
                                    shape="circle"
                                    icon={<ExportOutlined />}
                                    onClick={this.exportImage} />
                            </Tooltip> */}
            </Space>
          </Header>

          <Layout>
            <Content>
              <ResizeObserver
                onResize={this.onResize}>
                <div style={{
                  width: '100%',
                  height: '100%',
                }}>
                  <ReactEcharts
                    ref={this.echartRef}
                    style={{
                      width: state.contentWidth + 'px',
                      height: state.contentHeight + 'px',
                    }}
                    notMerge={true}
                    showLoading={state.loading}
                    loadingOption={{ text: '数据加载中' }}
                    opts={{ locale: 'ZH' }}
                    option={this.state.chartOption} />
                </div>
              </ResizeObserver>
            </Content>

            <Sider
              collapsed={state.tableCollapsed}
              trigger={null}
              collapsible
              collapsedWidth={0}
              width={state.tableWidth}
              style={{
                background: '#fafafa',
              }}>
              <VirtualTable
                size='small'
                pagination={false}
                scroll={{
                  y: tableScrollY,
                }}
                loading={state.loading}
                dataSource={state.tableData}
                columns={state.tableColumn} />
            </Sider>
          </Layout>

          {state.planDialogOpen &&
            <PlanDialog
              open={state.planDialogOpen}
              plan={state.plan}
              onCancel={this.hidePlanDialog}
              onSubmit={this.saveQueryPlan} />}
        </Layout>
      </div>
    )
  }
}

export default CurveChart